﻿/*================================================================
*   Copyright (C) 2023 baichao All rights reserved.
*
*   文件名称：common_oper.cpp
*   创 建 者：baichao
*   创建日期：2023年08月02日
*   描    述：
*
================================================================*/

#include <string> // string
#include <iostream> // cout, cerr
#include <cassert> // assert
#include "../../../leveldb/leveldb/leveldb/include/leveldb/db.h"
#include "../../../leveldb/leveldb/leveldb/include/leveldb/write_batch.h"
#include "../../../leveldb/leveldb/leveldb/include/leveldb/filter_policy.h"

int main()
{
    leveldb::DB *ldbptr = nullptr;
    leveldb::Options options;
    options.create_if_missing = true;
    options.filter_policy = leveldb::NewBloomFilterPolicy(10);
    
    const std::string db_path = "/var/tmp/baichao.db";
    std::string key = "key";
    std::string value = "value";

    leveldb::Status status = leveldb::DB::Open(options, db_path, &ldbptr);
    if(!status.ok()) {
        std::cerr << "open level db error:" << status.ToString() << std::endl;
        return 0;
    }
    assert(ldbptr != nullptr);
    std::cout << "open level db successfully !" << std::endl;

    // put insert
    int totals = 0;
    leveldb::WriteOptions putOptions;
    putOptions.sync = true;
    while(1)
    {
        std::string currKey = key + std::to_string(totals);
        std::string currValue = value + std::to_string(totals);
        const leveldb::Slice s_key = currKey;
        const leveldb::Slice s_value = currValue;
        
        status = ldbptr->Put(putOptions, s_key, s_value);
        if (!status.ok()) {
            std::cerr << "put data error:" << status.ToString() << std::endl;
            return 0;
        }
        totals++;
        if(totals % 1000 == 0)
        {
            std::cout << totals << std::endl;
        }

        if(totals == 200000)
        {
            break;
        }
        //std::cout << "put data successfully!" << std::endl;
    }

    // // test batch write
    // {
    //     leveldb::WriteBatch writeBatch;
    //     writeBatch.Put("username", "Joel");
    //     writeBatch.Put("gender", "Male");
    //     writeBatch.Put("job", "Programmer");

    //     status = ldbptr->Write(leveldb::WriteOptions(), &writeBatch);
    //     if (!status.ok()) {
    //         std::cerr << "batch write data error:" << status.ToString() << std::endl;
    //         return 0;
    //     }
    //     std::cout << "batch write data successfully!" << std::endl;
    // }

    // get test
    // {
    //     leveldb::ReadOptions getOptions;
    //     std::string rdVal;
    //     // Slice(const std::string& s)
    //     status = ldbptr->Get(getOptions, key, &rdVal);
    //     if (!status.ok()) {
    //         std::cerr << "get data error:" << status.ToString() << std::endl;
    //         return 0;
    //     }
    //     std::cout << "get data successfully:" << rdVal << std::endl;
    //     assert(value == rdVal);
    // }

    totals = 0;     
    leveldb::ReadOptions getOptions;
    while(1)
    {
        std::string currKey = key + std::to_string(totals);
        std::string currValue;
        const leveldb::Slice s_key = currKey ;
        //const leveldb::Slice s_value;
        
        status = ldbptr->Get(getOptions, s_key, &currValue);
        if (!status.ok()) {
            std::cerr << "get data error:" << status.ToString() << std::endl;
            return 0;
        }
        totals++;

        std::cout << "totals:" << totals << "; key:" << currKey << "; value:" << currValue << std::endl;

        if(totals == 200000)
        {
            break;
        }
        //std::cout << "put data successfully!" << std::endl;
    }

    // // test iterator
    // {
    //     leveldb::Iterator *iterator = ldbptr->NewIterator(leveldb::ReadOptions());
    //     if(!iterator) {
    //         std::cerr << "can not new iterator" << std::endl;
    //         return 0;
    //     }

    //     // caller must call one of the Seek methods on the iterator before using it
    //     iterator->SeekToFirst();
    //     std::cout << "=========== iterator begin ===========" << std::endl;
    //     while(iterator->Valid())
    //     {
    //         leveldb::Slice sKey = iterator->key();
    //         leveldb::Slice sVal = iterator->value();
    //         std::cout << "key:" << sKey.ToString() << "\tvalue:" << sVal.ToString() << std::endl;
    //         iterator->Next();
    //     }
    //     std::cout << "=========== iterator end ===========" << std::endl;

    //     // caller should delete the iterator when it is no longer needed
    //     delete(iterator);
    // }

    // caller should delete leveldb::DB ptr when it is no longer needed
    delete(ldbptr);

    std::cout << "test completed !" << std::endl;
    return 0;
}

